// wglcamera.cpp
//

#include "config.h"
#include "wgl/wglcamera.hpp"
#include "wgl/wgltransfo.hpp"

#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtx/euler_angles.hpp"

using namespace wgl;



// glm::mat4x4 model = glm::mat4x4( 1.0f );
// glm::mat4x4 view =
//   glm::lookAt( glm::vec3( -5.0f, 3.0f, -10.0f ), glm::vec3( 0.0f, 0.0f, 0.0f ), glm::vec3( 0.0f, -1.0f, 0.0f ) );
// glm::mat4x4 projection = glm::perspective( glm::radians( 45.0f ), 1.0f, 0.1f, 100.0f );
// // clang-format off
// glm::mat4x4 clip = glm::mat4x4( 1.0f,  0.0f, 0.0f, 0.0f,
//                                 0.0f, -1.0f, 0.0f, 0.0f,
//                                 0.0f,  0.0f, 0.5f, 0.0f,
//                                 0.0f,  0.0f, 0.5f, 1.0f );  // vulkan clip space has inverted y and half z !
// // clang-format on
// glm::mat4x4 mvpc = clip * projection * view * model;



// Camera::Camera
//
Camera::Camera ( CameraType type )
  : type(type)
{
}



// Camera::get_matrix
//
const glm::mat4 &Camera::get_matrix ()
{
  if (proj_dirty || view_dirty)
    {
      if (proj_dirty)
        {
          m_proj = glm::perspective(fov, aspect_ratio, z_near, z_far);
          proj_dirty = false;
        }
      if (view_dirty)
        {
          // [FIXME]
          Transfo tr{position, rotation, glm::vec3{1.f, 1.f, 1.f}};
          m_view = tr.get_inverse();
          view_dirty = false;
        }
      m_vp = m_proj * m_view;
    }
  return m_vp;
}



// Camera::set_fov
//
void Camera::set_fov ( float fov )
{
  this->fov = fov;
  proj_dirty = true;
}



// Camera::set_aspect_ratio
//
void Camera::set_aspect_ratio ( float aspect_ratio )
{
  this->aspect_ratio = aspect_ratio;
  proj_dirty = true;
}



// Camera::set_z_clip
//
void Camera::set_z_clip ( float z_near,
                          float z_far )
{
  this->z_near = z_near;
  this->z_far = z_far;
  proj_dirty = true;
}



// Camera::set_position
//
void Camera::set_position ( glm::vec3 position )
{
  this->position = position;
  view_dirty = true;
}



// Camera::set_rotation
//
void Camera::set_rotation ( glm::vec3 rotation )
{
  this->rotation = rotation;
  view_dirty = true;
}
